package com.homelock.service;

import java.util.*;
import java.util.stream.Collectors;

import com.alibaba.fastjson.JSONObject;
import com.homelock.common.enumeration.ServiceTypeEnum;
import com.homelock.common.enumeration.TriggerTypeEnum;
import com.homelock.constants.OpmodeEnum;
import com.homelock.constants.UnlockAttributeEnum;
import com.homelock.constants.ZxUserTypeEnum;
import com.homelock.dto.HlOpenDoorRecordDto;
import com.homelock.dto.HuaWeiIotRecord;
import com.homelock.entity.*;
import com.homelock.thread.AlarmSmsAsyncTask;
import com.pi.base.enumerate.record.RecordState;
import com.pi.base.exception.ServiceException;
import org.apache.http.util.Asserts;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;

import com.homelock.domain.query.OpenRecordQuery;
import com.homelock.entity.HlOpenDoorRecordExample.Criteria;
import com.homelock.mapper.HlOpenDoorRecordMapper;
import com.homelock.vo.OpenDoorRecordVO;
import com.pi.base.util.time.DateTools;
import org.springframework.util.StringUtils;

@Service
public class LockOpenRecordService {
  private static final Logger logger = LoggerFactory.getLogger(LockOpenRecordService.class);

  @Autowired
  private HlOpenDoorRecordMapper hlOpenDoorRecordMapper;
  @Autowired
  private LockUserService lockUserService;
  @Autowired
  private HlDevInfoService hlDevInfoService;
  @Autowired
  private AlarmSmsAsyncTask alarmSmsAsyncTask;
  @Autowired
  private HlDevUserUnlockService hlDevUserUnlockService;
  @Autowired
  private HlFamilyLinkageService hlFamilyLinkageService;

  public List<OpenDoorRecordVO> queryOpenRecordList(OpenRecordQuery openRecordQuery){
    HlOpenDoorRecordExample example = new HlOpenDoorRecordExample();
    Criteria criteria = example.createCriteria();
    List<HlDevUser> userLockList = lockUserService.queryUserLockList(openRecordQuery.getOperateUserId());
    if(CollectionUtils.isEmpty(userLockList)) {
      return new ArrayList<OpenDoorRecordVO>(0);
    }
    Map<Long, HlDevUser> devUserMap = userLockList.stream().collect(Collectors.toMap(HlDevUser::getDevId, devUser -> devUser));
    if(null != openRecordQuery.getDevId()) {
      if(!devUserMap.containsKey(openRecordQuery.getDevId())) {
        return new ArrayList<OpenDoorRecordVO>(0);
      }
      criteria.andDevIdEqualTo(openRecordQuery.getDevId());
    }else {
      criteria.andDevIdIn(new ArrayList<>(devUserMap.keySet()));
    }
    if(null != openRecordQuery.getUserId()){
      criteria.andTriggerSourceIdEqualTo(openRecordQuery.getUserId());
    }
    if(null != openRecordQuery.getOpmode()){
      criteria.andTriggerTypeEqualTo(openRecordQuery.getOpmode());
    }
    if(null != openRecordQuery.getRecordType()){
      criteria.andRecordTypeEqualTo(openRecordQuery.getRecordType().byteValue());
    }
    criteria.andStateEqualTo(RecordState.STATE_NORMAL.getState());

    if(null != openRecordQuery.getLimit() && null != openRecordQuery.getOffset()){
      example.setOrderByClause(" create_date DESC LIMIT "+openRecordQuery.getOffset()+" , "+openRecordQuery.getLimit());
    }else{
      example.setOrderByClause(" create_date DESC ");
    }
    List<HlOpenDoorRecord> list = hlOpenDoorRecordMapper.selectByExample(example);
    if(!CollectionUtils.isEmpty(list)){
      // 设备名称
      List<HlDevInfo> devInfoList = hlDevInfoService.getDevInfoByIds(new ArrayList<>(devUserMap.keySet()));
      Map<Long, String> devNameMap = devInfoList.stream().collect(Collectors.toMap(HlDevInfo::getId, HlDevInfo::getDevName));
      List<OpenDoorRecordVO> voList = new ArrayList<>();
      for(HlOpenDoorRecord record : list){
        OpenDoorRecordVO vo = new OpenDoorRecordVO();
        vo.setDevName(devNameMap.get(record.getDevId()) == null ? "" :devNameMap.get(record.getDevId()));
        vo.setOpmode(record.getTriggerType()+"");
        vo.setOpTime(DateTools.getFullDate(record.getCreateDate()));
        vo.setStatus("2");
        // 查询当前开门用户信息
        if(record.getTriggerSourceId() != null && record.getTriggerSourceId() != 0L){
          vo.setUserName("");
          vo.setOpenName(queryUserName(record));
        }else{
          vo.setUserName("");
          vo.setOpenName(record.getTriggerName());
        }
        vo.setTriggerName(record.getTriggerName());
        voList.add(vo);
      }
      return voList;
    }
    return new ArrayList<>(0);
  }

    /**
     * 查询振兴锁的开门记录
     * 没有用户概念 只有某个门锁的开门记录列表
     * @param openRecordQuery
     * @return
     */
    public List<OpenDoorRecordVO> queryZxOpenRecordList(OpenRecordQuery openRecordQuery){
        List<HlDevUser> userLockList = lockUserService.queryUserLockList(openRecordQuery.getOperateUserId());
        if(CollectionUtils.isEmpty(userLockList)) {
            return new ArrayList<OpenDoorRecordVO>(0);
        }
       HlOpenDoorRecordExample example = new HlOpenDoorRecordExample();
        Criteria criteria = example.createCriteria();
        Map<Long, HlDevUser> devUserMap = userLockList.stream().collect(Collectors.toMap(HlDevUser::getDevId, devUser -> devUser));
        if(null != openRecordQuery.getDevId()) {
            if(!devUserMap.containsKey(openRecordQuery.getDevId())) {
                return new ArrayList<OpenDoorRecordVO>(0);
            }
            criteria.andDevIdEqualTo(openRecordQuery.getDevId());
        }else {
            criteria.andDevIdIn(new ArrayList<>(devUserMap.keySet()));
        }
        if(null != openRecordQuery.getOpmode()){
            criteria.andTriggerTypeEqualTo(openRecordQuery.getOpmode());
        }
        if(null != openRecordQuery.getRecordType()){
            criteria.andRecordTypeEqualTo(openRecordQuery.getRecordType().byteValue());
        }
        criteria.andStateEqualTo(RecordState.STATE_NORMAL.getState());

        if(null != openRecordQuery.getLimit() && null != openRecordQuery.getOffset()){
            example.setOrderByClause(" id DESC LIMIT "+openRecordQuery.getOffset()+" , "+openRecordQuery.getLimit());
        }else{
            example.setOrderByClause(" id DESC ");
        }
        List<HlOpenDoorRecord> list = hlOpenDoorRecordMapper.selectByExample(example);
        if(!CollectionUtils.isEmpty(list)){
            List<HlDevInfo> devInfoList = hlDevInfoService.getDevInfoByIds(new ArrayList<>(devUserMap.keySet()));
            Map<Long, String> devNameMap = devInfoList.stream().collect(Collectors.toMap(HlDevInfo::getId, HlDevInfo::getDevName));

            // HlDevInfo hlDevInfo = hlDevInfoService.getDevInfobyId(openRecordQuery.getDevId());
            List<OpenDoorRecordVO> voList = new ArrayList<>();
            for(HlOpenDoorRecord record : list){
                OpenDoorRecordVO vo = new OpenDoorRecordVO();
                vo.setDevName(Optional.ofNullable(devNameMap.get(record.getDevId())).orElse(""));
                vo.setOpmode(record.getTriggerType()+"");
                vo.setOpTime(DateTools.getFullDate(record.getCreateDate()));
                vo.setStatus("2");
                // 查询当前开门用户信息
                if(record.getTriggerId() != null && record.getTriggerId() != 0L){
                    // 查询振兴锁可能涉及到修改的名称
                    //HlDevUserUnlock unlock = hlDevUserUnlockService.queryById(record.getTriggerSourceId());
                    HlDevUserUnlock unlock = hlDevUserUnlockService.findOneByDevIdAnUnlockIdAndStatusTrue(record.getDevId(),
                            record.getTriggerId()+"");
                    vo.setUserName("");
                    if(unlock == null || StringUtils.isEmpty(unlock.getUnlockName())){
                        if(record.getTriggerId() == 0L){
                            vo.setOpenName(ZxUserTypeEnum.UNDEFINED_USER.getDesc());
                        }else{
                            vo.setOpenName(record.getTriggerId()+"");
                        }
                    }else{
                        vo.setOpenName(unlock.getUnlockName());
                    }
                  //  vo.setOpenName(Optional.ofNullable(unlock).map(HlDevUserUnlock::getUnlockName).orElse(ZxUserTypeEnum.UNDEFINED_USER.getDesc()));

                }else{
                    // 有一种情况是未知用户开门 sourceId=0
                    if(record.getRecordType() == ServiceTypeEnum.MESSAGE.getType().byteValue()){
                        vo.setOpenName(ZxUserTypeEnum.UNDEFINED_USER.getDesc());
                    }else{
                        vo.setOpenName(record.getTriggerName());
                    }
                    vo.setUserName("");
                    // 普通开门上传的就是id
                  //  vo.setOpenName(String.valueOf(record.getTriggerId()));
                }
                vo.setTriggerName(record.getTriggerName());
                voList.add(vo);
            }
            return voList;
        }
        return new ArrayList<>(0);
    }



  /**
   * 插入推送记录
   * @param recordObject
   * @return
   */
  @Transactional
  public boolean insertLockOpenRecord(JSONObject recordObject){
    // 验证对象
    HuaWeiIotRecord record = checkInsertRecord(recordObject);
    if(record == null || StringUtils.isEmpty(record.getNotifyType()) || "deviceDatasChanged".equals(record.getNotifyType())){
      logger.error("NotifyType不匹配，忽略开门记录");
      return false;
    }
    // 构造本地存储数据对象,根据imei查询
    HlDevInfo hlDevInfo = hlDevInfoService.getDevInfoByImei(record.getImei());
    // 根据imei查询不到门锁 关联失败 存储失败
    if(hlDevInfo == null){
      logInsertError("本地数据库查询不到该锁具["+record.getImei()+"]信息",recordObject.toJSONString());
      return false;
    }
    // 查询到本地设备idhomelock-zx-1.0.0.jar
    Long devId = hlDevInfo.getId();
    // 数据转换
    List<HlOpenDoorRecord> recordList = HlOpenDoorRecordDto.convertRecord(record,devId);
    if(recordList.size() == 0){
      logger.info("推送消息解析不出任何开门记录或者报警记录，存储0条记录");
      return false;
    }
    for(HlOpenDoorRecord item:recordList){
      // 获取关联用户id 区分是普通开门还是报警开门
      item = fingerOrPwdOrCardRecord(item);
      item.setCommunityId(hlDevInfo.getCommunityId());
      item.setSourceId(hlDevInfo.getSourceId());
      hlOpenDoorRecordMapper.insertSelective(item);
      logger.info("一条记录存储成功："+item.toString());
      sendAlarmSms(item,devId,hlDevInfo);
      sendFamilySms(item,devId,hlDevInfo);
    }
    return true;
  }

  private HlOpenDoorRecord fingerOrPwdOrCardRecord(HlOpenDoorRecord record){
    if(StringUtils.isEmpty(record.getTriggerUserId())){
      return record;
    }
    // 指纹开门check转换
    record = changeRecordEnitity(true,record,TriggerTypeEnum.FINGER_OPEN,OpmodeEnum.UNLOCK_FINGER.getOpmode(),TriggerTypeEnum.FINGER_ALARM);
    // 密码开门check转换
    record = changeRecordEnitity(true,record,TriggerTypeEnum.PWD_OPEN,OpmodeEnum.UNLOCK_PASSWPRD.getOpmode(),TriggerTypeEnum.PWD_ALARM);
    // 卡片开门check转换
    record = changeRecordEnitity(false,record,TriggerTypeEnum.CARD_OPEN,OpmodeEnum.UNLOCK_CARD.getOpmode(),null);
    // 蓝牙开门 sourceId即用户id
    if(record.getTriggerType() == TriggerTypeEnum.BLUETOOH_OPEN.getCode()){
      Long sourceId = 0L;
      try {
        sourceId = Long.valueOf(record.getTriggerUserId());
      }catch (Exception e){
      }
      record.setTriggerSourceId(sourceId);
    }
    return record;
  }


  /**
   * 查询当前密码/指纹/蓝牙等userId为非用户id，查询关联id
   *  同时根据关联id是否为报警类型
   * @param record
   * @param equalTrigeerEnum
   * @param queryOpMode
   * @param setTriggerTypeEnum
   * @return
   */
  private HlOpenDoorRecord changeRecordEnitity(boolean checkAlarm,HlOpenDoorRecord record,TriggerTypeEnum equalTrigeerEnum,byte queryOpMode,TriggerTypeEnum setTriggerTypeEnum){
    if(record.getTriggerType() == equalTrigeerEnum.getCode()) {
      // 查询当前设备指纹/密码/卡片信息
      HlDevUserUnlock userUnlock = hlDevUserUnlockService.queryByDevIdAndUnlockTypeAndUnlockId(record.getDevId(),
              queryOpMode, record.getTriggerUserId());
      if (userUnlock == null) {
        return record;
      }
      record.setTriggerUnlockId(userUnlock.getId());
      if(record.getTriggerType() == TriggerTypeEnum.FINGER_OPEN.getCode()) {
        record.setTriggerSourceId(userUnlock.getDevUserId());
      }else{
        record.setTriggerSourceId(userUnlock.getId());
      }
      if (checkAlarm && userUnlock.getUnlockAttribute() == UnlockAttributeEnum.ALARM.getAttribute()) {
        // 指纹报警 需要更改当前记录类型
        record.setRecordType(ServiceTypeEnum.Alarm.getType().byteValue());
        record.setTriggerType(setTriggerTypeEnum.getCode());
        record.setTriggerName(setTriggerTypeEnum.getName());
      }
    }
    return record;
  }

  /**
   * 发送报警短信模块
   * @param item
   * @param devId
   * @param hlDevInfo
   */
  private void sendAlarmSms(HlOpenDoorRecord item,Long devId,HlDevInfo hlDevInfo){
    // check 报警类型
    if (!StringUtils.isEmpty(hlDevInfo.getOwnerId()) && (item.getTriggerType() == TriggerTypeEnum.RETRY_FORBIDDEN_ALARM.getCode()
            || item.getTriggerType() == TriggerTypeEnum.PICK_ALARM.getCode()
            || item.getTriggerType() == TriggerTypeEnum.FINGER_ALARM.getCode()
            || item.getTriggerType() == TriggerTypeEnum.PWD_ALARM.getCode())){
        // 验证当前锁是否有注册人
       HlDevUser hlDevOwner = lockUserService.queryLockUserByDevIdAndUserId(devId,hlDevInfo.getOwnerId());
      // 当前锁具没有注册人 则无需发送短信
      if(hlDevOwner != null){
        String openUserName = "";
        if(item.getTriggerType() == TriggerTypeEnum.FINGER_ALARM.getCode() && item.getTriggerSourceId() != 0L){
          // 指纹报警，查询当前触发对象
          HlDevUser hlDevUser = lockUserService.queryByIdAndDevId(item.getTriggerSourceId(),devId);
          openUserName = (hlDevUser == null) ? "" :hlDevUser.getDevUserName();
        }
        // 异步发送报警短信
        alarmSmsAsyncTask.runAlarmSmsAsyncTask(TriggerTypeEnum.val(item.getTriggerType()),hlDevInfo,openUserName);
      }else{
          logger.info("[SendAlarmSms]:该锁已经被清空，没有注册人，无需发送短信");
      }
    }
  }

  /**
   * 发送亲情短信模块
   * 蓝牙开门-有开门用户的微信id
   * 指纹开门-有开门用户的devUserId
   * @param item
   * @param devId
   * @param hlDevInfo
   */
  private void sendFamilySms(HlOpenDoorRecord item,Long devId,HlDevInfo hlDevInfo) {
    logger.info("[SendFamilySms]:"+item.getTriggerType());
    // 蓝牙开门有开门用户，指纹开门有开门用户
    if (!StringUtils.isEmpty(hlDevInfo.getOwnerId())
            && (item.getTriggerType() == TriggerTypeEnum.BLUETOOH_OPEN.getCode()
            || item.getTriggerType() == TriggerTypeEnum.FINGER_OPEN.getCode())) {
      HlDevUser sendUser;
      if (item.getTriggerType() == TriggerTypeEnum.BLUETOOH_OPEN.getCode()) {
        // 蓝牙开门
        sendUser = lockUserService.queryLockUserByDevIdAndUserId(devId, item.getTriggerSourceId());
      } else {
        // 指纹开门
        sendUser = lockUserService.queryByIdAndDevId(item.getTriggerSourceId(), devId);
      }
      if (sendUser == null) {
        logger.info("[SendFamilySms]:该开门记录查询不到蓝牙或者指纹对应的开门用户，无需发送亲情短信");
        return;
      }
      List<HlFamilyLinkage> receiverList = hlFamilyLinkageService.queryTargetUserByDevIdAndUserId(devId, sendUser.getId());
      if(CollectionUtils.isEmpty(receiverList)){
        logger.info("[SendFamilySms]:该开门记录对应的开门用户无亲情关联，无需发送亲情短信");
        return;
      }
    // 异步发送亲情短信
    alarmSmsAsyncTask.runFamilySmsAsyncTask(hlDevInfo,sendUser,receiverList);

    }
  }

  /**
   * 开门记录：查询开门相关用户名称
   * @return
   */
  private String queryUserName(HlOpenDoorRecord record){
    if(record.getTriggerType() == TriggerTypeEnum.FINGER_OPEN.getCode() ||
            record.getTriggerType() == TriggerTypeEnum.FINGER_ALARM.getCode() ){
      // 指纹开锁 userId是devUser的id
      HlDevUser fingerUser = lockUserService.queryByIdAndDevId(record.getTriggerSourceId(),record.getDevId());
      if(fingerUser != null && !StringUtils.isEmpty(fingerUser.getDevUserName())){
        return new StringBuffer("").append(fingerUser.getDevUserName())
          .append("的").append(record.getTriggerName()).toString();
      }
      return record.getTriggerName();
    }else if(record.getTriggerType() == TriggerTypeEnum.BLUETOOH_OPEN.getCode()){
      // 蓝牙的用户是wechat userId
       HlDevUser openUser = lockUserService.queryLockUserByDevIdAndUserId(record.getDevId(),record.getTriggerSourceId());
       if(openUser != null ){
          return new StringBuffer("").append(openUser.getDevUserName()).append("的").append(record.getTriggerName()).toString();
        }
       return record.getTriggerName();
     }
    // 门卡 密码开锁
    HlDevUserUnlock hlDevUserUnlock = hlDevUserUnlockService.queryById(record.getTriggerSourceId());
    if(hlDevUserUnlock != null && !StringUtils.isEmpty(hlDevUserUnlock.getUnlockName())){
      return new StringBuffer("").append(hlDevUserUnlock.getUnlockName()).append("开锁").toString();
    }
    return record.getTriggerName();
  }

  /**
   * check推送对象
   * @param jsonObject
   * @return
   */
  private HuaWeiIotRecord checkInsertRecord(JSONObject jsonObject){
    Assert.notNull(jsonObject,"推送对象为空");
    HuaWeiIotRecord record = JSONObject.parseObject(jsonObject.toJSONString(),HuaWeiIotRecord.class);
     // jsonObject.toJavaObject(HuaWeiIotRecord.class);
    String checkMsg = record.checkValidate();
    if(checkMsg.length() > 0){
      logInsertError(checkMsg,jsonObject.toJSONString());
      throw new ServiceException(checkMsg);
    }
    return record;
  }

  private void logInsertError(String errorMsg,String object){
    logger.error("[推送数据存储失败][err:{}][data:{}]",errorMsg,object);
  }

    public void clearByDevId(Long devId) {
        // TODO Auto-generated method stub
        HlOpenDoorRecordExample example = new HlOpenDoorRecordExample();
        example.createCriteria().andDevIdEqualTo(devId).andStateEqualTo(RecordState.STATE_NORMAL.getState());
        HlOpenDoorRecord record = new HlOpenDoorRecord();
        record.setState(RecordState.STATE_DELETE.getState());
        hlOpenDoorRecordMapper.updateByExampleSelective(record, example);
    }

  /**
   * 新增振兴锁的开门记录
   * @param record
   */
  public void insertZxLock(HlOpenDoorRecord record){
    Date date = new Date();
    record.setCreateDate(date);
    record.setUpdateDate(date);
    record.setState(RecordState.STATE_NORMAL.getState());
    record.setVersion(1L);
    hlOpenDoorRecordMapper.insertSelective(record);
  }
}
